package services;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import repositories.RouteRepository;
import domain.Administrator;
import domain.Event;
import domain.Route;

@Service
@Transactional
public class RouteService {

	// Managed repository -----------------------------------------------------
	@Autowired
	private RouteRepository routeRepository;
	
	@Autowired
	private AdministratorService administratorService;
	
	// Constructor ------------------------------------------------------------
	public RouteService(){
		super();
	}
	
	// Simple CRUD methods ----------------------------------------------------
	public Route create(Event e){
		Administrator a = administratorService.findByPrincipal();
		Assert.notNull(a.getEvents());
		Assert.notNull(e);
		Route r = new Route();
		r.setEvent(e);
		return r;
	}
	
	public void save(Route r){
		Assert.notNull(r,"tried to save a null route");
		
		checkPrincipal(r,"tried to modify a route property of other administrator");
		
		//Comprobar que no existe ya una ruta con el mismo orden que la que se pretende guardar
		Event routeEvent = r.getEvent();
		Collection<Route> existentRoutes = routeEvent.getRoutes();
		for (Route route:existentRoutes){
			Assert.isTrue(r.getId()!=0 ||r.getOrderNumber()!=route.getOrderNumber(),"tried to save a route with an existent order value");
		}
		
		this.routeRepository.save(r);
	}
	
	public void delete(Route r){
		Assert.notNull(r,"tried to delete a null route");
		Assert.isTrue(this.routeRepository.exists(r.getId()),"tried to delete a route that doesn't exists");
		checkPrincipal(r,"tried to delete a route property of other administrator");
		
		this.routeRepository.delete(r);
	}
	
	public Collection<Route> findAll(){
		return routeRepository.findAll();
	}
	
	// Other business methods -------------------------------------------------
	public Route findOne(int id){
		Assert.isTrue(id!=0,"tried to find a route with id zero");
		
		Route res = this.routeRepository.findOne(id);
		Assert.notNull(res,"found route is null");
		
		return res;
	}
	
	public Collection<Route> findRoutesByEvent(Event e){
		Assert.notNull(e,"tried to find routes of an event that doesn't exists");
		Assert.isTrue(e.getId()!=0,"tried to find routes of an event with id zero");
		
		Collection<Route> res;
		
		res = this.routeRepository.findRoutesByEvent(e.getId());
		Assert.notNull(res,"event routes collection found is null");
		
		return res;
	}
	
	public Collection<Route> findAllByAdministrator(Administrator a){
		Assert.notNull(a, "tied to find routes of a null administrator");
		Assert.isTrue(a.getId()!=0, "tried to find routes of and administrator with id zero");
		
		Collection<Route> res;
		
		res = this.routeRepository.findAllByAdmin(a.getId());
		Assert.notNull(res,"admin routes collection found is null");
		
		return res;
	}
	
	private void checkPrincipal(Route route, String message){
		Administrator principal = administratorService.findByPrincipal();
		Assert.isTrue(principal.equals(route.getEvent().getAdministrator()),message);
	}

	public void saveRating(Route r) {
		Assert.notNull(r,"tried to save a null route");
		Assert.isTrue(administratorService.findByPrincipal()!=null);
		this.routeRepository.save(r);
		
	}
	
	// Form object related methods ---------------------------------------------
		public Boolean itsHacked (Route r){
			Boolean res = true;
			
			Route persistedOne = routeRepository.findOne(r.getId());
			if(r.getEvent()==null || persistedOne.getEvent().equals(r.getEvent()))
				res = false;
				
			return res;
		}
}
